﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\DataTypes\EnArray.cs
 * Description  :      An array with any number of dimension
 * Change log   :     -2011: First version (originally, it was part of SimGine library)
 * To Do        :
 ************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections;
using SMLib.Base;

namespace SMLib.DataTypes
{
    /// <summary>
    /// An array with any number of dimension
    /// </summary>
    /// <typeparam name="T">Type of elements: it can be enum, primitive data type of IStateVariable</typeparam>
    public class EnArray<T> : IStateVariable
    {

        T[] array;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="firstDimentionSize"></param>
        /// <param name="sizes"></param>
        public EnArray(int firstDimentionSize, params int[] sizes)
        {
            if (!(typeof(T).IsPrimitive || (typeof(T) == typeof(string)) || (typeof(T).IsEnum)
                || (typeof(T).GetInterface(typeof(IStateVariable).FullName) != null)))
                throw new Exception("The type of T in EnQueue<T> should be builtin, string or IStateVariable!");

            if (sizes.Length > 0)
            {
                throw new Exception("Not implemented yet!");
            }
            array = new T[firstDimentionSize];
        }

        /// <summary>
        /// Length of the array in a particular dimention
        /// </summary>
        /// <param name="dimention"></param>
        /// <returns></returns>
        public int Length(int dimention = 0)
        {
            if (dimention == 0)
                return array.Length;
            throw new Exception("Not Implemented Yet!");
        }

        /// <summary>
        /// Convert to string
        /// </summary>
        /// <returns>the string representation of EnArray</returns>
        public override string ToString()
        {
            string st = "{";
            for (int i = 0; i < array.Length; i++)
                st += ((i > 0) ? "," : "") + array[i].ToString();
            st += "}";
            return st;

        }

        /// <summary>
        /// The equality check method
        /// </summary>
        /// <param name="obj">the other object</param>
        /// <returns>true if equal, false in other case</returns>
        public override bool Equals(object obj)
        {
            if (this.GetType() != obj.GetType())
                return false;
            EnArray<T> secondobj = obj as EnArray<T>;
            if (this.array.Length != secondobj.array.Length)
                return false;
            for (int i = 0; i < array.Length; i++)
            {
                if (!array[i].Equals(secondobj.array[i]))
                    return false;
            }
            return true;
        }

        /// <summary>
        /// The object in a partcular place
        /// </summary>
        /// <param name="index1"></param>
        /// <param name="indexes"></param>
        /// <returns></returns>
        public T this[int index1, params int[] indexes]
        {
            get
            {
                if (indexes.Length != 0)
                    throw new Exception("Not implemented yet!");
                return array[index1];
            }
            set
            {
                if (indexes.Length != 0)
                    throw new Exception("Not implemented yet!");
                array[index1] = value;
            }
        }

        /// <summary>
        /// Get enumarator of the object
        /// </summary>
        /// <returns>the enumarator</returns>
        public IEnumerator GetEnumerator()
        {
            return array.GetEnumerator();
        }

        /// <summary>
        /// Get the hash code of this array
        /// </summary>
        /// <returns>the hashcode value</returns>
        public override int GetHashCode()
        {
            //To Do:[implement this function]
            return base.GetHashCode();
        }

        /// <summary>
        /// Clone the array
        /// </summary>
        /// <returns>a clone version of the current object</returns>
        public object Clone()
        {
            EnArray<T> obj = new EnArray<T>(array.Length);
            if ((typeof(T)).IsPrimitive || typeof(T).IsEnum || typeof(T) == typeof(string))
            {
                for (int i = 0; i < array.Length; i++)
                    obj.array[i] = array[i];
            }
            else if (typeof(T) is ICloneable)
            {
                for (int i = 0; i < array.Length; i++)
                    obj.array[i] = (T)(((ICloneable)array[i]).Clone());
            }
            return obj;
        }


        #region IState Members


        public object[] Fields
        {
            get { return null; }
        }

        public string GetLocationName(int locationId)
        {
            if (locationId == 0)
                return "No-Name";
            else
                return null;
        }

        public int LocationValuesCount
        {
            get { return 1; }
        }

        public object GetLocation(int locationId)
        {
            if (locationId == 0)
                return array;
            else
                return null;
        }

        #endregion

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj.Equals(this))
                return 0;
            else
                return -1;
        }

        #endregion
    }
}
